<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>理解闭包</title>
</head>
<body>
<script>
    //闭包的常见创建方式就是在一个函数内部创建另一个函数，通过另一个函数访问这个函数的局部变量。

    function f1() {
        var times = 0;

        function f2() {
            return ++times;
        }

        return f2;
    }

    var fff = f1();
    // console.log(fff());//1
    // console.log(fff());//2
    // console.log(fff());//3
    // console.log(fff());//4
    fff = null;
    //释放当前变量
    //闭包就是函数内部和函数外部链接的一座桥梁

    //上述案例，利用闭包函数实现了全局作用域中访问局部变量times,并让变量的值始终存储在内存中.
    //在第19行代码调用f1()函数后，将匿名函数的引用返回给fff变量，且匿名函数中使用了局部变量times.
    //因此，局部变量times不会在fn1()函数执行完成后被Javascript回收，依然保存在内存中。


    function Person(name) {
        var age;//私有属性方法

        //私有方法
        function setAge(n) {
            age = n;
            //不要乱修改私有属性的age属性
        }

        function getAge() {
            return age;
        }

        return {
            name: name,
            setAge: setAge,
            getAge: getAge
        }
    }

    var p1 = Person();
    p1.setAge(18);
    // console.log(p1.getAge());
    p1 = null;//置空释放

    //IIFE ()是表达式  跟在函数后面 表示调用函数fn()
    //立即执行函数：定义函数之后，立即调用该函数，这种函数叫做立即执行函数
    //注意：如果function出现在行首  一律解释成函数的声明语句
    //简称：自执行函数
    //常见的两种写法
    (function () {
    })();
    !(function () {
    }());
    //通常情况下  写自执行函数的时候
    !(function () {

    })();

    //1.全局变量,会污染这个全局的变量
    // var a = 0;
    // function add() {
    //     return ++a;
    // }
    // console.log(add());
    // console.log(add());
    // console.log(add());
    // console.log(add());
    // console.log(add());

    //2.自定义属性
    // function add() {
    //     return ++add.count;
    // }
    // add.count=0;//X对于后面有些代码可能会无意修改其值
    // console.log(add());
    // console.log(add());
    // console.log(add());
    // console.log(add());

    //立即执行函数也叫闭包，可以封装私有的属性，同时可以减少全局变量的污染
    var add = (function () {
        //私有属性不会被污染
        var count = 0;
        return function () {
            return ++count;
        }
    })();
    // console.log(add());
    // console.log(add());
    // console.log(add());
    // console.log(add());

    //解决方案 使用闭包解决循环中变量的问题，相当于把变量保存在内存中，每次执行的时候从内存中获取
    function count() {
        var arr = [];
        for (var i = 0; i < 10; i++) {
            // arr[i] = (function (n) {
            //     return n;
            // })(i);

            // (function (n) {
            //     arr[n] = (function () {
            //         return n;
            //     })
            // })(i);


        }
        return arr;
    }

    // var c = count();
    // console.log(c[0]());
    // console.log(c[1]);
    // console.log(c[2]);
    //let块级作用域
    // {
    //     let zz=45;
    // }
    // console.log(zz);

    //1.返回值


    //2.函数赋值

    //3.函数参数

    //4.IIFE

    //5.循环赋值

    //6.getter和setter

    //7.迭代器

    //8.区分首次

    //9.缓存机制

    //10.img对象图片上报

</script>
</body>
</html>